package procsim;

import java.awt.*;
import java.util.*;
import java.awt.image.*;
import java.text.*;
import java.awt.font.*;

public class GBigMSignal extends BigMSignal implements GraphicalLine {

    private LinkedHashMap<Coords, ImageObserver> coords;
    private boolean displayName = false;

    public GBigMSignal(int numOfBits){
        super(numOfBits);
        coords = new LinkedHashMap<Coords, ImageObserver>();
    }

    public GBigMSignal(int numOfBits, boolean display){
        super(numOfBits);
        coords = new LinkedHashMap<Coords, ImageObserver>();
        displayName = display;
    }

    public GBigMSignal(int numOfBits, String name){
        super(numOfBits, name);
        coords = new LinkedHashMap<Coords, ImageObserver>();
    }

    public GBigMSignal(int numOfBits, String name, boolean display){
        super(numOfBits, name);
        coords = new LinkedHashMap<Coords, ImageObserver>();
        displayName = display;
    }

    public GBigMSignal(int numOfBits, int value) {
        super(numOfBits, value);
        coords = new LinkedHashMap<Coords, ImageObserver>();
    }

    public GBigMSignal(int numOfBits, int value, boolean display) {
        super(numOfBits, value);
        coords = new LinkedHashMap<Coords, ImageObserver>();
        displayName = display;
    }

    public GBigMSignal(int numOfBits, int value, String name) {
        super(numOfBits, value, name);
        coords = new LinkedHashMap<Coords, ImageObserver>();
    }

    public GBigMSignal(int numOfBits, int value, String name, boolean display) {
        super(numOfBits, value, name);
        coords = new LinkedHashMap<Coords, ImageObserver>();
        displayName = display;
    }

    public Color getColor(){
        if(get() == 0) return Color.BLUE;
        else if (getNumOfBits()>1) return Color.GREEN;
        else return Color.RED;
    }

    @Override
    public GBigMSignal addCoords(ImageObserver observer, Coords coor){
        coords.put(coor, observer);
        return this;
    }

    @Override
    public GBigMSignal addCoords(ImageObserver observer, int x1, int y1, int x2, int y2){
        coords.put(new Coords(x1, y1, x2, y2), observer);
        return this;
    }

    @Override
    public void drawIt(Graphics2D g, ImageObserver observer) {
        Util.saveGraphics(g);
        ArrayList<Coords> prevcoords = new ArrayList<Coords>();
        Iterator iter = coords.keySet().iterator();
        while(iter.hasNext()) {
            Coords drawing = (Coords)iter.next();
            ImageObserver tmp = coords.get(drawing);
            if(tmp!=observer) continue;
            g.setColor(new Color(70, 70, 70));
            //g.setFont(new Font("Arial", Font.BOLD, 12));
            if(displayName && writeName(drawing, prevcoords)){
                if(drawing.getX1() > drawing.getX2() || drawing.getY1() > drawing.getY2()){
                    if(drawing.getX1() - drawing.getX2() > drawing.getY1() - drawing.getY2())
                        g.drawString(getAttributedName().getIterator(), drawing.getX1()-32, drawing.getY1()-2);
                    else
                        g.drawString(getAttributedName().getIterator(), drawing.getX1()+2, drawing.getY1()-25);
                }
                else {
                    if(drawing.getX2() - drawing.getX1() > drawing.getY2() - drawing.getY1())
                        g.drawString(getAttributedName().getIterator(), drawing.getX1()+2, drawing.getY1()-3);
                    else
                        g.drawString(getAttributedName().getIterator(), drawing.getX1()+2, drawing.getY1()+12);
                }
            }
            prevcoords.add(drawing);
            g.setColor(getColor());
            g.setStroke(new BasicStroke(2));
            g.drawLine(drawing.getX1(), drawing.getY1(), drawing.getX2(), drawing.getY2());
        }
        Util.restoreGraphics(g);
    }

    private boolean writeName(Coords drawing, ArrayList<Coords> all){
        Iterator iter = all.iterator();
        while(iter.hasNext()) {
            Coords cur = (Coords)iter.next();
            if(cur.getX1()==cur.getX2() &&
                drawing.getY1()==drawing.getY2() &&
                (drawing.getX1()==cur.getX1() || drawing.getX2()==cur.getX2()) &&
                ((cur.getY1()>cur.getY2() && ((cur.getY1()>=drawing.getY1() && cur.getY2()<=drawing.getY1()))) ||
                (cur.getY1()<cur.getY2() && ((cur.getY1()<=drawing.getY1() && cur.getY2()>=drawing.getY1())))))
                return false;
            if(cur.getY1()==cur.getY2() &&
                drawing.getX1()==drawing.getX2() &&
                (drawing.getY1()==cur.getY1() || drawing.getY2()==cur.getY2()) &&
                ((cur.getX1()>cur.getX2() && ((cur.getX1()>=drawing.getX1() && cur.getX2()<=drawing.getX1()))) ||
                (cur.getX1()<cur.getX2() && ((cur.getX1()<=drawing.getX1() && cur.getX2()>=drawing.getX1())))))
                return false;
        }
        return true;
    }

    private AttributedString getAttributedName(){
        AttributedString attName = new AttributedString(getName());
        int start = 0, end = 0;
        if(getName().contains("..")){
            char[] temp = new char[getName().length()];
            temp = getName().toCharArray();
            for(int i = 0; i < temp.length; i++){
                if(Character.isDigit(temp[i])){
                    start = i;
                    break;
                }
            }
            end = getName().length();
            attName.addAttribute(TextAttribute.SIZE, 9, start, end);
        }
        return attName;
    }
}
